# 该文件实现使用过程中的一些基础用法
import csv
import pandas as pd
import numpy as np
import ast
import json
from collections import defaultdict
from difflib import SequenceMatcher
pd.set_option('display.max_columns', None)  # 显示所有列
pd.set_option('display.width', 1000)        # 设置显示宽度
pd.set_option('display.max_colwidth', 100)  # 设置列内容的最大显示宽度



# 字符检查
# 返回包含所有包含指定子字符串的字符串的列表
def find_elements_with_substrings(lst, substrings):
    results = {substring: [] for substring in substrings}
    for element in lst:
        for substring in substrings:
            if substring in element:
                results[substring].append(element)
                break  # 如果找到一个子串匹配就停止在当前元素上的检查
    return results
#分组
def group_by_prefix(lst):
        groups = defaultdict(list)
        for item in lst:
            prefix = item[:8]  # 取前八个字符作为前缀
            groups[prefix].append(item)
        return list(groups.values())

#  最长子串函数
def longest_common_substring(s1, s2):
    matcher = SequenceMatcher(None, s1, s2)
    match = matcher.find_longest_match(0, len(s1), 0, len(s2))
    return s1[match.a: match.a + match.size]















# 全部类型的数据读取
def df_get(deal_path,person,test):
    '''
    返回该deal中对应的df,输入例如1008-1-1
    :param deal_path: 文件存储路径
    :param person: 名称编号
    :param test: 实验编号
    :return:(ecg_df,rrdata_df,ppg_df,rri_df,singlework_df,singledetail_df) 返回对应的文件读取后的df（全部为字符串读取），可增加对应的类型
    '''


    path=deal_path+'\\'+person+'\\'+test

    ecg_df=pd.read_csv(path+'-ecg.csv',dtype=str)
    rrdata_df=pd.read_csv(path+'-rrdata.csv',dtype=str)
    ppg_df=pd.read_csv(path+'-ppg.csv',dtype=str)
    rri_df=pd.read_csv(path+'-rri.csv',dtype=str)
    singlework_df=pd.read_csv(path+'-singlework.csv',dtype=str)
    singledetail_df=pd.read_csv(path+'-singledetail.csv',dtype=str)


    return (ecg_df,rrdata_df,ppg_df,rri_df,singlework_df,singledetail_df)
#最大心率
def max_hr(df):
    '''
    # 输入为 df  ，
    # ，输入一个rrdata 的df，
    #  可用全局ecg的最大心率，也可用于每个阶段的最大心率，还可用于singledeail阶段的最大心率
    :param df:  rrdata_df或  rrdata的一部分
    :param hr_col:  hr所在的列名
    :return: 最大心率  str
    '''
    data = df.iloc[:, 1].astype('int64').tolist()

    # 滑动窗口参数
    window_size = 10
    step_size = 1

    # 存储滑动窗口的平均值
    rolling_means = []

    # 计算滑动窗口的平均值
    for i in range(0, len(data) - window_size + 1, step_size):
        window = data[i:i + window_size]
        window_mean = sum(window) / window_size
        rolling_means.append(window_mean)

    # 找到最大的平均值
    max_mean = max(rolling_means) if rolling_means else None

    # 输出结果
    # print("滑动窗口的平均值列表：")
    # print(rolling_means)
    print("心率最大的平均值：")
    print(max_mean)
    return max_mean




def stage_divide(ecg_df):
    '''
    # 跑步阶段划分,并实现每个阶段的标注，方便之后处理
    #输入合并后完整的ecg，输出 一个df 包括每个阶段的stage，开始时间，结束时间，心理rpe，生理rpe
    #可在此步做检查判断每个阶段的时间差和阶段与阶段之间的时间差，从而得到检查该数据是否有问题
    #循环该df也可以得到对应阶段的df，或函数内部也有 groupe  可作为输出
    :param ecg_df:
    :return: df:每个阶段的一个开始结束阶段等
    example:
        stage               start_time                 end_time    start_stamp      end_stamp psychology_RPE physiology_RPE      name
0       1  2024-07-26 09:51:32.275  2024-07-26 09:59:45.463  1721958692275  1721959185463              0              0      rest
1       2  2024-07-26 10:02:43.744  2024-07-26 10:12:51.666  1721959363744  1721959971666              0              0    warmup
2       3  2024-07-26 10:14:55.401  2024-07-26 10:20:05.269  1721960095401  1721960405269              1              1   running
3       4  2024-07-26 10:20:51.956  2024-07-26 10:25:56.202  1721960451956  1721960756202              1              1   running
4       5  2024-07-26 10:26:41.199  2024-07-26 10:31:44.879  1721960801199  1721961104879              2              2   running
5       6  2024-07-26 10:32:26.504  2024-07-26 10:37:31.309  1721961146504  1721961451309              2              2   running
6       7  2024-07-26 10:38:23.619  2024-07-26 10:43:27.862  1721961503619  1721961807862              2              3   running
7       9  2024-07-26 10:45:19.222  2024-07-26 10:50:24.031  1721961919222  1721962224031              3              3   running
8      10  2024-07-26 10:51:09.592  2024-07-26 10:56:14.403  1721962269592  1721962574403              4              3   running
9      11  2024-07-26 10:57:10.651  2024-07-26 11:02:17.715  1721962630651  1721962937715              5              5   running
10     12  2024-07-26 11:03:07.776  2024-07-26 11:08:14.278  1721962987776  1721963294278              6              6   running
11     13  2024-07-26 11:09:18.400  2024-07-26 11:14:23.216  1721963358400  1721963663216              8              8   running
12     14  2024-07-26 11:15:59.395  2024-07-26 11:21:05.337  1721963759395  1721964065337              9              9   running
13     15  2024-07-26 11:22:40.954  2024-07-26 11:27:43.526  1721964160954  1721964463526             10             10   running
14     16  2024-07-26 11:29:30.392  2024-07-26 11:32:47.789  1721964570392  1721964767789              2              2     stand
15     17  2024-07-26 11:33:26.041  2024-07-26 11:38:37.602  1721964806041  1721965117602              2              2  run_rest
    '''
    stage=[]
    df=ecg_df
    df.iloc[:, 0] = df.iloc[:, 0].apply(lambda x: int(str(x)[:13]))
    df['change'] = (df['stage'].ne(df['stage'].shift()) & (df['psychology_RPE']=='-') & (df['stage']!='-')).cumsum()
    df['ecg_time'] = pd.to_datetime(df.iloc[:, 0], unit='ms', utc=True).dt.tz_convert('Asia/Shanghai')
    df['ecg_time'] = df['ecg_time'].dt.strftime('%Y-%m-%d %H:%M:%S.%f').str[:-3]
    grouped = df.groupby('change')
    # print(df)
    for name, group in grouped:
        stagegroup=group[group['stage']!="-"]


        rpegroup=group[group['psychology_RPE']!="-"]
        # print(group)

        # print(len(stagegroup),len(rpegroup))
        if len(stagegroup)>0 and len(rpegroup)>0:
            start_stamp=stagegroup.iloc[0,0]
            end_stamp=stagegroup.iloc[-1,0]
            start=stagegroup.iloc[0,6]
            end=stagegroup.iloc[-1,6]
            xlrpe=rpegroup.iloc[-1,3]
            slrpe=rpegroup.iloc[-1,4]
            # print(name,"开始为",start,'结束为',end)
            # print("rpe",xlrpe,'and',slrpe)
            stage.append([name,start,end,start_stamp,end_stamp,xlrpe,slrpe])
    df=pd.DataFrame(stage)


    df.columns=['stage','start_time','end_time','start_stamp','end_stamp','psychology_RPE','physiology_RPE']
    state=["rest", "warmup", "running", "stand", "run_rest"]


    def get_stage_label(stage_value, num_stages):
        if stage_value == 1:
            return 'rest'
        elif stage_value == 2:
            return 'warmup'
        elif stage_value == int(num_stages)-1:
            return 'stand'
        elif stage_value == num_stages:
            return 'run_rest'
        else:
            return 'running'
    num_stages = df['stage'].iloc[-1]
    df['name']=df['stage'].apply(lambda x: get_stage_label(x, num_stages))

    return df







def get_stage_rr(rrdata_df,rri_df,start_time,end_time,step):
    '''
    #返回每个阶段的rrdata与rri的序列，step  前后时间间隔step 单位秒
    :param rrdata_df:
    :param rri_df:
    :param start_time: 开始时间
    :param end_time: 结束时间
    :param step: 前后截取
    :return:
    example:两个列表，带时间戳
    1:[[1718604976460, 706], [1718604977166, 733], [1718604977583, 703], [1718604978705, 747], [1718604979266, 768],]
    [[1718604976861, 1214], [1718604977827, 966], [1718604978523, 696], [1718604979184, 661], [1718604979929, 745],]
    '''
    #     从给的stagedf中获取，获取每个阶段的开始和结束时间
    rrdata_df['timestamp'] = rrdata_df['timestamp'].astype('int64')
    rri_df['timestamp'] = rri_df['timestamp'].astype('int64')

    #   循环找到每个阶段的df
    step = step * 1000
    stage_rrdata = rrdata_df[(rrdata_df['timestamp'] > start_time + step) & (rrdata_df['timestamp'] < end_time - step)]
    stage_rri = rri_df[(rri_df['timestamp'] > start_time+ step) & (rri_df['timestamp'] < end_time - step) & (rri_df['sqi'] == '100')]


    stage_rrdata['combined'] = stage_rrdata.apply(lambda row: [row['timestamp'], row['rr']], axis=1)
    stage_rrdata2=stage_rrdata['combined'].tolist()

    if len(stage_rri)>=2:
        stage_rri['combined']=stage_rri.apply(lambda row: [row['timestamp'], row['value']], axis=1)
        rri_result =[[int(item[0]), int(item[1])] for item in stage_rri['combined'].tolist()]
    else:
        rri_result=[]


    rr_result = []

    # 处理数据
    for item in stage_rrdata2:
        # 使用eval将字符串转换为实际的列表对象
        list_obj = eval(item[1])
        # 使用filter去除空值，并转换为整数
        cleaned_list = list(map(int, filter(None, [x.strip() for x in list_obj])))

        # 对每个整数值生成一个新的子列表，并添加到结果列表中
        for i,value in enumerate(cleaned_list):
            if i == 0:
                rr_result.append([int(item[0]), value])
            else:
                previous = cleaned_list[i - 1]

                rr_result.append([int(item[0])+previous, value])

    print('rrresult',rr_result)
    # print('rriresult',rri_result)


    # stage_rri2 = [int(item) for item in stage_rri['value'].tolist() if item != '0']

    return rr_result,rri_result

def compar_stage_rr(rrdata_df,rri_df,start_time,end_time,step):
    '''
    #    写出对比功能,需要 对比  rr数量,
    :param rrdata_df:
    :param rri_df:
    :param start_time:
    :param end_time:
    :param step:
    :return:对比结果
    example：{'均值': [765.047703180212, 786.115823817292, 2.7164280580862226], '标准差': [84.27953605861333, 128.91429063138904, 41.87246438207381], 'rr个数': [566, 1226, 73.66071428571429], '中位数': [759.0, 763.0, 0.5256241787122208], 'nn50占比': [0.1501766784452297, 0.1631321370309951, 8.270088772365568], '差值的均方根（RMSSD）': [41.07831932521182, 94.88271600201149, 79.14678870649416], 'nn50个数': [85, 200, 80.7017543859649], 'sd1': [29.072390316969692, 67.11938368310405, 79.10654265739021], 'sd2': [117.40305982869056, 176.0263696864439, 39.957348487248225]}

    '''
    stage_rrdata2,stage_rri2=get_stage_rr(rrdata_df,rri_df,start_time,end_time,step)


    print(stage_rrdata2)
    # print(stage_rri2)

    outcome=compar_rr_sequence(stage_rrdata2,stage_rri2)
    # print(outcome)
    # 返回对比后的结果df
    return  outcome

def get_stage_signal(ppg_df,ecg_df,start_time,end_time,step):
    singledetail_df=ppg_df
    rrdata_df=ecg_df
    rrdata_df['ecg_timestamp'] = rrdata_df['ecg_timestamp'].astype('int64')
    singledetail_df['PPG_TIME'] = singledetail_df['PPG_TIME'].astype('int64')

    # print(singledetail_df)
    #   循环找到每个阶段的df
    step = step * 1000
    stage_rrdata = rrdata_df[(rrdata_df['ecg_timestamp'] > start_time + step) & (rrdata_df['ecg_timestamp'] < end_time - step)]

    stage_singledetail = singledetail_df[
        (singledetail_df['PPG_TIME'] > start_time + step) & (singledetail_df['PPG_TIME'] < end_time - step)]

    stage_rrdata['combined'] = stage_rrdata.apply(lambda row: [row['ecg_timestamp'], row['voltage']], axis=1)
    # print(stage_rrdata)
    polar_hr = [[item[0], float(item[1])] for item in stage_rrdata['combined'].tolist()]

    if len(stage_singledetail) >= 2:
        stage_singledetail['combined'] = stage_singledetail.apply(lambda row: [row['PPG_TIME'], row['GREEN1']], axis=1)
        huawei_hr = [[item[0], float(item[1])] for item in stage_singledetail['combined'].tolist()]
    # print(stage_singledetail)
    else:
        huawei_hr=[]
    print('ecg',polar_hr)
    print('ppg',huawei_hr)

    return huawei_hr,polar_hr

def get_stage_hr(rrdata_df,singledetail_df,start_time,end_time,step):
    '''
       同理
       :param rrdata_df:
       :param singledetail_df:
       :param start_time:
       :param end_time:
       :return:
       '''
    #     从给的stagedf中获取，获取每个阶段的开始和结束时间
    rrdata_df['timestamp'] = rrdata_df['timestamp'].astype('int64')
    singledetail_df['timestamp'] = singledetail_df['timestamp'].astype('int64')

    # print(singledetail_df)
    #   循环找到每个阶段的df
    step = step * 1000
    stage_rrdata = rrdata_df[(rrdata_df['timestamp'] > start_time+step) & (rrdata_df['timestamp'] < end_time-step)]
    stage_singledetail = singledetail_df[
        (singledetail_df['timestamp'] > start_time+step) & (singledetail_df['timestamp'] < end_time-step)]



    stage_rrdata['combined'] = stage_rrdata.apply(lambda row: [row['timestamp'], row['HR']], axis=1)
    polar_hr =[[int(item[0]), int(item[1])] for item in stage_rrdata['combined'].tolist()]
    if len(stage_singledetail) >= 2:
        stage_singledetail['combined'] = stage_singledetail.apply(lambda row: [row['timestamp'], row['心率']], axis=1)

    huawei_hr= [[int(item[0]), int(item[1])] for item in stage_singledetail['combined'].tolist()]
    print(polar_hr)
    print(huawei_hr)

    return polar_hr,huawei_hr
# 对比hr
def compar_stage_hr(rrdata_df,singledetail_df,start_time,end_time,step):
    hr_stage_rrdata, hr_stage_singledetail=get_stage_hr(rrdata_df,singledetail_df,start_time,end_time,step)
    # print(hr_stage_rrdata)
    # print(hr_stage_singledetail)
    outcome=compar_hr_sequence(hr_stage_rrdata,hr_stage_singledetail)

    # 返回一个序列
    return  outcome
# 两个rr序列的对比指标
def compar_rr_sequence(rrdata,rri):
    '''

    :param rrdata:
    :param rri:
    :return:
    '''


    # 个数
    rrdata_lenth=len(rrdata)
    rri_lenth=len(rri)
    # 均值
    rrdata_mean=np.mean(rrdata)
    rri_mean=np.mean(rri)
    # print('均值',rrdata_mean,rri_mean)
    #中位数
    rrdata_median = np.median(rrdata)
    rri_median = np.median(rri)
    # 标准差
    rrdata_std = np.std(rrdata, ddof=1)
    rri_std = np.std(rri, ddof=1)
    # 两个序列之间均方误差
    # mse = mean_squared_error(rrdata, rri)
    # 相邻RR间期差值的均方根（RMSSD）
    rrdata_rmssd = np.sqrt(np.mean(np.diff(rrdata) ** 2))
    rri_rmssd = np.sqrt(np.mean(np.diff(rri) ** 2))
    # ** NN50和pNN50 **：相邻RR间期差值大于50毫秒的次数（NN50），以及NN50占总RR间期的比例（pNN50）。
    nn50_1 = np.sum(np.abs(np.diff(rrdata)) > 50)
    nn50_2 = np.sum(np.abs(np.diff(rri)) > 50)
    pnn50_1 = nn50_1 / len(rrdata)
    pnn50_2 = nn50_2 / len(rri)


    # sd1和sd2
    def poincare_analysis(rr_sequence):
        rr_diff = np.diff(rr_sequence)
        sd1 = np.sqrt(np.std(rr_diff, ddof=1) ** 2 / 2)
        sd2 = np.sqrt(2 * np.std(rr_sequence, ddof=1) ** 2 - 0.5 * sd1 ** 2)
        return sd1, sd2

    rrdata_sd1, rrdata_sd2 = poincare_analysis(rrdata)
    rri_sd1, rri_sd2 = poincare_analysis(rri)

    outcome={'rr个数':[rrdata_lenth,rri_lenth],'均值':[rrdata_mean,rri_mean],'中位数':[rrdata_median,rri_median],'标准差':[rrdata_std,rri_std],'差值的均方根（RMSSD）':[rrdata_rmssd,rri_rmssd],
            'nn50个数':[nn50_1,nn50_2],'nn50占比':[pnn50_1 ,pnn50_2 ],'sd1':[rrdata_sd1,rri_sd1],'sd2':[rrdata_sd2,rri_sd2]}
    for key in outcome:
        if  isinstance(outcome[key], list):

            a=outcome[key][0]
            b=outcome[key][1]
            outcome[key].append(abs(a - b) / ((a + b) / 2) * 100)


    return outcome

def compar_hr_sequence(rrdata,singledetail):
    '''

    :param rrdata:
    :param singledetail:
    :return:
    '''
    rrdata=[int(x) for x in rrdata]
    singledetail=[int(x) for x in singledetail]
    # 个数

    rrdata_lenth = len(rrdata)
    rri_lenth = len(singledetail)
    # 均值
    rrdata_mean = np.mean(rrdata)
    rri_mean = np.mean(singledetail)
    # print('均值', rrdata_mean, rri_mean)
    # 中位数
    rrdata_median = np.median(rrdata)
    rri_median = np.median(singledetail)
    # 标准差
    rrdata_std = np.std(rrdata, ddof=1)
    rri_std = np.std(singledetail, ddof=1)




    outcome={'hr个数':[rrdata_lenth,rri_lenth],'均值':[rrdata_mean,rri_mean],'中位数':[rrdata_median,rri_median],'标准差':[rrdata_std,rri_std]
    }
    for key in outcome:
        if  isinstance(outcome[key], list):

            a=outcome[key][0]
            b=outcome[key][1]
            outcome[key].append(abs(a - b) / ((a + b) / 2) * 100)

    return outcome






def compar_all(all_df):
    '''
    全部数据对比，未完成
    :param all_df:
    :return:
    '''
    # print(all_df.columns)
    column_ecgrr = all_df['rr'].dropna().tolist()
    column_ecghr =all_df['HR'].dropna().tolist()
    column_ppgrr=all_df['value'].dropna().tolist()
    column_ppghr=all_df['心率'].dropna().tolist()
    # print(column_ecgrr)
    # column_ecgrr=[item for sublist in column_ecgrr for item in sublist if item != '']
    merged_ecgrr = []
    for string_list in column_ecgrr:
        # 将字符串转换为实际的列表对象
        actual_list = ast.literal_eval(string_list)
        # 过滤非空字符串并添加到 merged_list 中
        merged_ecgrr.extend([item.strip() for item in actual_list if item.strip()])
    # print(merged_ecgrr)
    # print(column_ppgrr)


    # print(column_ecghr)
    # print(column_ppghr)
    import matplotlib.pyplot as plt
    import numpy as np
    import matplotlib.pyplot as plt
    from scipy.interpolate import CubicSpline
    data = np.array([int(value) for value in column_ppghr])

    # 剔除异常值
    filtered_data = []
    for i in range(len(data)):
        if i < 10 or i >= len(data) - 10:
            # 处理前10个和最后10个数据点，直接加入
            filtered_data.append(data[i])
        else:
            # 计算前后10个取样点的30%的范围
            range30 = 0.3 * (data[i - 5:i + 6].max() - data[i - 5:i +6].min())
            if abs(data[i] - np.median(data[i - 5:i + 6])) <= range30:
                filtered_data.append(data[i])

    filtered_data = np.array(filtered_data)

    # 使用三次样条插值
    x = np.arange(len(filtered_data))
    cs = CubicSpline(x, filtered_data)

    # 绘制原始数据和插值结果
    plt.figure(figsize=(30, 15))

    # 原始数据
    plt.plot(x, filtered_data, 'o', label='Original Data')

    # 插值结果
    x_interp = np.linspace(0, len(filtered_data) - 1, 100)
    plt.plot(x_interp, cs(x_interp), '-', label='Cubic Spline Interpolation')

    # 设置图形标题和标签
    plt.title('Cubic Spline Interpolation after Outlier Removal')
    plt.xlabel('Index')
    plt.ylabel('Value')

    # 添加网格和图例
    plt.grid(True)
    plt.legend()

    # 显示图形
    plt.show()

    plt.show()




    return  ''





